﻿// <copyright file="VfsSourcePathEntry.cs" company="Sinclair Community College">
// Copyright 2010 Sinclair Community College
// </copyright>
// <originalAuthor>Patrick S. Seymour (patrick.seymour@gmail.com)</originalAuthor>

namespace SinclairCC.AppV
{
    using System;
    using System.Diagnostics.CodeAnalysis;

    /// <summary>
    /// This class represents a VFS source path entry in section 0x06 of a CP file.
    /// </summary>
    internal class VfsSourcePathEntry
    {
        /// <summary>
        /// The size of the entry block in total number of bytes.
        /// </summary>
        private int entrySize;
        
        /// <summary>
        /// This field contains the size of the entry block header (i.e. all the data before path strings).
        /// </summary>
        private int entryBlockHeaderSize;
        
        /// <summary>
        /// This field is reserved and is initialized to all zeroes.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "This field is marked as reserved in the App-V File Format Specification.")]
        private int reserved;
        
        /// <summary>
        /// The number of subentries (file names) following this entry.
        /// </summary>
        /// <remarks>
        /// Files always have zero subentries, whereas directories always have one
        /// or more subentries (an entry for a directory cannot have a zero subentry
        /// so directories without files cannot be fully virtualized).
        /// </remarks>
        private int subEntryCount;
        
        /// <summary>
        /// The relative byte offset to the full (long) filename for the directory
        /// or file inside entry block.
        /// </summary>
        /// <remarks>
        /// The offset is relative to the beginning of the entry block header.
        /// </remarks>
        private int nameOffset;

        /// <summary>
        /// The size of the full filename in bytes.
        /// </summary>
        private int nameSize;
        
        /// <summary>
        /// The relative byte offset to the short (max 8+3) filename for the directory
        /// or file inside entry block.
        /// </summary>
        private int shortNameOffset;

        /// <summary>
        /// The size of the short filename in bytes.
        /// </summary>
        private int shortNameSize;

        /// <summary>
        /// The short file name for the entry.
        /// </summary>
        private string shortFileName;

        /// <summary>
        /// The long file name for the entry.
        /// </summary>
        private string longFileName;

        /// <summary>
        /// Initializes a new instance of the VfsSourcePathEntry class.
        /// </summary>
        /// <param name="dataStream">
        /// A MemoryStream containing the raw data for the VFS source path entry.
        /// </param>
        public VfsSourcePathEntry(System.IO.MemoryStream dataStream)
        {
            this.shortFileName = string.Empty;
            this.longFileName = string.Empty;
            this.ReadSection(dataStream);
        }

        /// <summary>
        /// Gets the short file name for the entry.
        /// </summary>
        public string ShortFileName
        {
            get { return this.shortFileName; }
        }

        /// <summary>
        /// Gets the long file name for the entry.
        /// </summary>
        public string LongFileName
        {
            get { return this.longFileName; }
        }

        /// <summary>
        /// Reads the actual data for this section from the file.
        /// </summary>
        /// <param name="dataStream">
        /// A MemoryStream containing the raw data for the VFS source path entry.
        /// </param>
        private void ReadSection(System.IO.MemoryStream dataStream)
        {
            System.IO.BinaryReader streamReader = new System.IO.BinaryReader(dataStream);

            this.entrySize = streamReader.ReadInt32();
            this.entryBlockHeaderSize = streamReader.ReadInt32();
            this.reserved = streamReader.ReadInt32();
            this.subEntryCount = streamReader.ReadInt32();
            this.nameOffset = streamReader.ReadInt32();
            this.nameSize = streamReader.ReadInt32();
            this.shortNameOffset = streamReader.ReadInt32();
            this.shortNameSize = streamReader.ReadInt32();

            this.shortFileName = System.Text.Encoding.Unicode.GetString(streamReader.ReadBytes(this.shortNameSize));
            this.longFileName = System.Text.Encoding.Unicode.GetString(streamReader.ReadBytes(this.nameSize));
        }
    }
}
